﻿/*
REWRITTEN FROM SCRATCH BY XINEF, IT OWNS NOW!
*/

#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "naxxramas.h"
#include "Player.h"
#pragma execution_character_set("utf-8")

enum Says
{
    SAY_AGGRO                   = 0,
    SAY_SLAY                    = 1,
    SAY_TAUNT                   = 2,
    SAY_DEATH                   = 3
};

enum Spells
{
	SPELL_SPELL_DISRUPTION			= 29310,
	SPELL_DECREPIT_FEVER_10			= 29998,
	SPELL_DECREPIT_FEVER_25			= 55011,
	SPELL_PLAGUE_CLOUD				= 29350,
};

enum Events
{
	EVENT_SPELL_SPELL_DISRUPTION	= 1,
	EVENT_SPELL_DECEPIT_FEVER		= 2,
	EVENT_ERUPT_SECTION				= 3,
	EVENT_SWITCH_PHASE				= 4,
	EVENT_SAFETY_DANCE				= 5,
};

enum Misc
{
	PHASE_SLOW_DANCE				= 0,
	PHASE_FAST_DANCE				= 1,
};

class boss_heigan : public CreatureScript
{
public:
    boss_heigan() : CreatureScript("boss_heigan") { }

    CreatureAI* GetAI(Creature* pCreature) const
    {
        return new boss_heiganAI (pCreature);
    }

	struct boss_heiganAI : public ScriptedAI
	{
		boss_heiganAI(Creature *c) : ScriptedAI(c)
		{
			pInstance = me->GetInstanceScript();
		}

		InstanceScript* pInstance;
		EventMap events;
		uint8 currentPhase;
		uint8 currentSection;
		bool moveRight;

		void Reset()
		{
			events.Reset();
			currentPhase = 0;
			currentSection = 3;
			moveRight = true;

			if (pInstance)
			{
				pInstance->SetData(EVENT_HEIGAN, NOT_STARTED);
				if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_HEIGAN_ENTER_GATE)))
					go->SetGoState(GO_STATE_ACTIVE);
			}
		}

		void KilledUnit(Unit* who)
		{
			if (who->GetTypeId() != TYPEID_PLAYER)
				return;

			if (!urand(0,3))
				Talk(SAY_SLAY);

			if (pInstance)
				pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
		}

		void JustDied(Unit* Killer)
		{
			Talk(SAY_DEATH);
			if (pInstance)
				pInstance->SetData(EVENT_HEIGAN, DONE);
		}

		void EnterCombat(Unit *who)
		{
			me->SetInCombatWithZone();
			Talk(SAY_AGGRO);
			if (pInstance)
			{
				pInstance->SetData(EVENT_HEIGAN, IN_PROGRESS);
				if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_HEIGAN_ENTER_GATE)))
					go->SetGoState(GO_STATE_READY);
			}

			StartFightPhase(PHASE_SLOW_DANCE);
		}

		void StartFightPhase(uint8 phase)
		{
			currentSection = 3;
			currentPhase = phase;
			events.Reset();
			if (phase == PHASE_SLOW_DANCE)
			{
				events.ScheduleEvent(EVENT_SPELL_SPELL_DISRUPTION, 0);
				events.ScheduleEvent(EVENT_SPELL_DECEPIT_FEVER, 12000);
				events.ScheduleEvent(EVENT_ERUPT_SECTION, 10000);
				events.ScheduleEvent(EVENT_SWITCH_PHASE, 90000);
			}
			else // if (phase == PHASE_FAST_DANCE)
			{
				me->MonsterTextEmote("%s 传送并且开始引导一道法术!", 0, true);
				// teleport
				float x, y, z, o;
				me->GetHomePosition(x, y, z, o);
				me->NearTeleportTo(x, y, z, o);

				me->CastSpell(me, SPELL_PLAGUE_CLOUD, false);
				events.ScheduleEvent(EVENT_ERUPT_SECTION, 4000);
				events.ScheduleEvent(EVENT_SWITCH_PHASE, 45000);
			}
			events.ScheduleEvent(EVENT_SAFETY_DANCE, 5000);
		}

		bool IsInRoom(Unit* who)
		{
			if (who->GetPositionX() > 2826 || who->GetPositionX() < 2723 || who->GetPositionY() > -3641 || who->GetPositionY() < -3736)
			{
				if (who->GetGUID() == me->GetGUID())
					EnterEvadeMode();
				return false;
			}

			return true;
		}

		void UpdateAI(uint32 diff)
		{
			if (!IsInRoom(me))
				return;

			if (!UpdateVictim())
				return;

			events.Update(diff);
			//if (me->HasUnitState(UNIT_STATE_CASTING))
			//	return;

			switch (events.GetEvent())
			{
				case EVENT_SPELL_SPELL_DISRUPTION:
					me->CastSpell(me, SPELL_SPELL_DISRUPTION, false);
					events.RepeatEvent(10000);
					break;
				case EVENT_SPELL_DECEPIT_FEVER:
					me->CastSpell(me, RAID_MODE(SPELL_DECREPIT_FEVER_10, SPELL_DECREPIT_FEVER_25), false);
					events.RepeatEvent(20000);
					break;
				case EVENT_SWITCH_PHASE:
					StartFightPhase(currentPhase == PHASE_SLOW_DANCE ? PHASE_FAST_DANCE : PHASE_SLOW_DANCE);
					// no pop, there is reset in start fight
					break;
				case EVENT_ERUPT_SECTION:
					if (pInstance)
					{
						pInstance->SetData(DATA_HEIGAN_ERUPTION, currentSection);
						if (currentSection == 3)
							moveRight = false;
						else if (currentSection == 0)
							moveRight = true;

						moveRight ? currentSection++ : currentSection--;
					}

					if (currentPhase == PHASE_SLOW_DANCE && !urand(0,3))
						Talk(SAY_TAUNT);

					events.RepeatEvent(currentPhase == PHASE_SLOW_DANCE ? 10000 : 4000);
					break;
				case EVENT_SAFETY_DANCE:
				{
					Map::PlayerList const& pList = me->GetMap()->GetPlayers();
					for(Map::PlayerList::const_iterator itr = pList.begin(); itr != pList.end(); ++itr)
					{
						if (IsInRoom(itr->GetSource()) && !itr->GetSource()->IsAlive())
						{
							events.PopEvent();
							pInstance->SetData(DATA_DANCE_FAIL, 0);
							pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
							return;
						}

					}
					events.RepeatEvent(5000);
					return;
				}
			}

			DoMeleeAttackIfReady();
		}
	};
};

void AddSC_boss_heigan()
{
	new boss_heigan();
}
